package com.stox.manager;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import com.stox.event.NewBarsEvent;
import com.stox.event.NewScripEvent;
import com.stox.model.Bar;
import com.stox.model.DataStream;
import com.stox.model.Exchange;
import com.stox.model.ExchangeDownloadMetadata;
import com.stox.model.Scrip;
import com.stox.provider.DataProvider;
import com.stox.util.Constant;

@Component
public class DownloadManager{
	
	@Autowired
	private DataProvider dataProvider;
	
	@Autowired
	private ApplicationEventPublisher applicationEventPublisher;

	@Autowired
	private ExchangeDownloadMetadataManager exchangeDownloadMetadataManager;

	private boolean cancelRequested;
	private boolean running;
	
	public DownloadManager() {
		Runtime.getRuntime().addShutdownHook(new Thread(){
			@Override
			public void run() {
				cancel();
			}
		});
	}
	
	public void cancel(){
		cancelRequested = true;
		while(running){
			Thread.yield();
		}
	}
	
	public boolean isRunning() {
		return running;
	}
	
	private ExchangeDownloadMetadata getExchangeDownloadMetadata(Exchange exchange) {
		ExchangeDownloadMetadata exchangeDownloadMetadata = 
				exchangeDownloadMetadataManager.findByExchangeCode(exchange.getCode());
		if(null == exchangeDownloadMetadata){
			exchangeDownloadMetadata = createExchangeDownloadMetadata(exchange);
		}
		return exchangeDownloadMetadata;
	}
	
	private ExchangeDownloadMetadata createExchangeDownloadMetadata(Exchange exchange) {
		ExchangeDownloadMetadata exchangeDownloadMetadata = new ExchangeDownloadMetadata();
		exchangeDownloadMetadata.setExchangeCode(exchange.getCode());
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.YEAR, -5);
		exchangeDownloadMetadata.setLastDownloadDate(calendar.getTime());
		return exchangeDownloadMetadataManager.save(exchangeDownloadMetadata);
	}
	
	private void updateLastDownloadDate(String exchangeCode, Date date) {
		ExchangeDownloadMetadata exchangeDownloadMetadata = 
				exchangeDownloadMetadataManager.findByExchangeCode(exchangeCode);
		exchangeDownloadMetadata.setLastDownloadDate(date);
		exchangeDownloadMetadataManager.save(exchangeDownloadMetadata);
		System.out.println("Downloaded : "+Constant.dateFormat.format(date));
	}
	
	private Calendar getLastDownloadDate(Exchange exchange) {
		ExchangeDownloadMetadata exchangeDownloadMetadata = getExchangeDownloadMetadata(exchange);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(exchangeDownloadMetadata.getLastDownloadDate());
		return calendar;
	}
	
	private void processDataStream(DataStream dataStream, Exchange exchange, Date date) {
		if (dataStream != null && dataStream.getBars() != null && !dataStream.getBars().isEmpty()) {
			for(Scrip scrip : dataStream.getScrips())
				applicationEventPublisher.publishEvent(new NewScripEvent<Scrip>(scrip));
			applicationEventPublisher.publishEvent(new NewBarsEvent<List<Bar>>(dataStream.getBars()));
			updateLastDownloadDate(exchange.getCode(), date);
		}
	}
	
	public void bredthDownload(final Exchange exchange) {
		if(cancelRequested || running) return;
		Calendar calendar = getLastDownloadDate(exchange);
		Date endDate = new Date();
		while (!calendar.getTime().after(endDate) && 
				!cancelRequested && (running = true)) {
			try {
				calendar.add(Calendar.DATE, 1);
				if (isWeekend(calendar)) continue;
				processDataStream(dataProvider.get(exchange,calendar.getTime()), exchange, calendar.getTime());
			} catch (Throwable t) {
				t.printStackTrace();
			}finally{
				running = false;
			}
		}
	}
	
	public boolean isWeekend(Calendar calendar){
		return Calendar.SUNDAY == calendar.get(Calendar.DAY_OF_WEEK) || 
				Calendar.SATURDAY == calendar.get(Calendar.DAY_OF_WEEK);
	}
	
}
